#include "Pawn.hpp"
#include "CriticalException.hpp"
#include "Cell.hpp"
#include "Chessboard.hpp"


#define C_CONTAINS_PIECE(POS, COLOR)																\
	((Chess::getInstance()->getChessboard()->getCell(POS)->hasPiece()) 								\
	 && (Chess::getInstance()->getChessboard()->getCell(POS)->getPiece()->getColor() == COLOR))


#define CELL_CONTAINS_PIECE_POS_CCOLOR()								\
	C_CONTAINS_PIECE((Position(xtmp, ytmp, color)), (this->color))


#define CELL_CONTAINS_PIECE_POS_OCOLOR()													\
	C_CONTAINS_PIECE(Position(xtmp, ytmp, color), Chess::oppositeColor(this->color))


Pawn::Pawn(Chess::Color color, const Position& pos)
	: Piece(color, Piece::PAWN, pos)
{}

Pawn::~Pawn()
{}


bool	Pawn::isPromotable() const
{
	if (this->isOut())
		return false;
	
	Position p = this->getCell()->getPosition();
	p.setColor(this->color);
	
	return (p.getY() == 7);
}

list<Position*>		Pawn::getPossibleCases() const
{
	if (this->isOut())
		throw new CriticalException("PAWN : getPossibleCases : THIS is out !");
	
	int x, y, xtmp, ytmp;
	
	list<Position*> valables;
	
	Position cur = this->getCell()->getPosition();
	
	cur.setColor(color);
	
	x = cur.getX();
	y = cur.getY();
		
	for (int i = -1; i < 2 ; i++)
	{
		xtmp = x + i;
		ytmp = y + 1;
		
		if (Position::isGood(xtmp, ytmp) && !(CELL_CONTAINS_PIECE_POS_CCOLOR()))
		{
			if (i == -1 || i == 1)
			{
				if (CELL_CONTAINS_PIECE_POS_OCOLOR())
					valables.push_back(new Position(xtmp, ytmp, color));
			}
			else
			{
				if (!CELL_CONTAINS_PIECE_POS_OCOLOR())
					valables.push_back(new Position(xtmp, ytmp, color));
			}
		}
		
		if (nb_movements == 0)
		{
			ytmp = y + 2;
			
			if (i == 0  && !C_CONTAINS_PIECE(Position(xtmp, (ytmp - 1), color), this->color)  
				&& !C_CONTAINS_PIECE(Position(xtmp, (ytmp - 1), color), Chess::oppositeColor(this->color)))
			{
				if (Position::isGood(xtmp, ytmp) && !C_CONTAINS_PIECE(Position(xtmp, ytmp, color), this->color)
					&& !C_CONTAINS_PIECE(Position(xtmp, ytmp, color), Chess::oppositeColor(this->color)))
					valables.push_back(new Position(xtmp, ytmp, color));		
			}
		}
	}
	
	return valables;
}

